package accounts.sync.array;

import java.util.HashMap;
import java.util.Random;

public class AccountsHandler {
	private class Accounts {
		private HashMap<Integer, Integer> map;

		@SuppressWarnings("unused")
		private Accounts() {
		};

		public Accounts(int number) {
			map = new HashMap<Integer, Integer>();
			for (int i = 0; i <= number; i++)
				map.put(i, 0);
		}

		public int get(int accountNumber) {
			return map.get(accountNumber);
		}

		public void set(int accountNumber, int sumToWithdraw) {
			map.put(accountNumber, sumToWithdraw);
		}

	}

	private Accounts accounts;
	private Object[] array;
	private final int MAX = 5;

	public AccountsHandler() {
		accounts = new Accounts(MAX);
		array = new Object[MAX];
		for (int i = 0; i < array.length; i++)
			array[i] = new Object();
	}

	private void depositMoney(int accountNumber, int sumToDeposit) {
		synchronized (array[accountNumber]) {
			int money = accounts.get(accountNumber);
			money += sumToDeposit;
			accounts.set(accountNumber, money);
		}
	}

	private void withdrawMoney(int accountNumber, int sumToWithdraw) {
		synchronized ( array[accountNumber]) {
			int money = accounts.get(accountNumber);
			money -= sumToWithdraw;
			accounts.set(accountNumber, money);
		}
	}

	private int getBalance(int accountNumber) {

		return accounts.get(accountNumber);
	}

	void transfer(int senderAccount, int receiverAccount, int sum) {

		this.withdrawMoney(senderAccount, sum);
		this.depositMoney(receiverAccount, sum);
	}

	public class BankThread extends Thread {
		private AccountsHandler ah;

		public BankThread(AccountsHandler ac) {
			ah = ac;
		}

		public void run() {
			int ac1, ac2;
			Random generator = new Random();
			ac1 = generator.nextInt(ah.MAX);
			ac2 = generator.nextInt(ah.MAX);

			ah.transfer(ac1, ac2, 100);
//			System.out.println("Transferred 100 $ from "
//					+ Integer.toString(ac1) + " to " + Integer.toString(ac2));
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		AccountsHandler ac = new AccountsHandler();
		BankThread thread;

		for (int i = 0; i < 100 * ac.MAX; i++) {
			thread = ac.new BankThread(ac);
			thread.start();
			try {
				thread.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		int sum = 0;
		for (int i = 0; i < ac.MAX; i++) {
			sum += ac.getBalance(i);
			System.out.println("The balance for account " + i + " = "
					+ ac.getBalance(i) + "$");
		}
		System.out.println("The total balance is " + sum + "$");
	}
}